//
// Created by F1997 on 2024/12/24.
//

#ifndef NETWORK_TRAFFIC_PROCESSING_V2_PCAPUTILS_H
#define NETWORK_TRAFFIC_PROCESSING_V2_PCAPUTILS_H
#include "pch.h"
#include "IniReader.h"
#include "headers.hpp"
#include "SafeQueueTemplate.h"
#include "CompareTraffic.h"
#include "SPMCQueueTemplate.h"
#include "ThreadPoolV2.hpp"


namespace ntp {

    // pcap抓包工具类
    class PcapUtils {
    public:
        PcapUtils() = default;

        // 列表初始化和优化，{}还是()???
        PcapUtils(std::shared_ptr<spdlog::logger> _my_logger, ShareDataClzz* _shareDataClzz) //, IniReader* _iniCfg, CompareTraffic _compareTraffic)
        //: my_logger(_my_logger), iniCfg(_iniCfg)
        //compareTraffic(_compareTraffic)
        {
            my_logger = _my_logger;
            //shareDataClzz = _shareDataClzz;
            //iniCfg = _iniCfg;
            //compareTraffic = new CompareTraffic(iniCfg);
            p_t = new ThreadPool(2);

        };

        void readPcapFile();

        bool checkIsStart(std::chrono::system_clock::time_point startTime, int offset);

        int readNetworkIfaceLine(std::string sectionId, std::chrono::system_clock::time_point startTime, IniReader* iniCfg, SafeQueue<MarketData>* data_queue);
        int readNetwork(std::string sectionId, std::chrono::system_clock::time_point startTime, IniReader* iniCfg);


        int readMsg(std::shared_ptr<spdlog::logger> my_logger, IniReader* iniCfg, SafeQueue<MarketData>* data_queue1, SafeQueue<MarketData>* data_queue2);
        int sampled(std::shared_ptr<spdlog::logger> _my_logger, IniReader* iniCfg);

        std::chrono::system_clock::time_point parseTime(const std::string& timeStr);
        std::chrono::system_clock::time_point string_to_time_point(const std::string& str);
        time_t parse_date_to_timestamp(const std::string& date_str);

        void parse_packet_dce(const struct pcap_pkthdr* pkthdr, const u_char* packet, MarketData& marketData); // MarketData& marketData
        void parse_packet_shfe(const struct pcap_pkthdr* pkthdr, const u_char* packet, MarketData& marketData); // MarketData& marketData
        void parse_packet_zce(const struct pcap_pkthdr* pkthdr, const u_char* packet, MarketData& marketData); // MarketData& marketData
        // 解析数据包
        void parse_packet2(const struct pcap_pkthdr* pkthdr, const u_char* packet);

    private:
        //ShareDataClzz* shareDataClzz;
        // 流量对比类
        std::shared_ptr<spdlog::logger> my_logger;
        //CompareTraffic compareTraffic;
        //CompareTraffic compareTraffic;
        ThreadPool* p_t;

#pragma pack(1)
// 小端序、1字节对齐
        // 结构体是由pcap_loop自己填充的，用来取得一些关于数据包的信息
        struct my_pcap_pkthdr {
            struct timeval ts;   /* 时间戳 */
            bpf_u_int32 caplen;   /* 已捕获部分的长度 */
            bpf_u_int32 len;  /* 该包的脱机长度 */
        };

        // 定义以太网头部结构，14字节
        struct my_ether_header {
            u_int8_t ether_dhost[6]; // 目的MAC地址
            u_int8_t ether_shost[6]; // 源MAC地址
            u_int16_t ether_type;    // 协议类型
        };

        // 定义IP头部结构，20字节
        struct my_ip_header {
            u_int8_t ip_hl : 4, ip_v : 4; // IP头部长度和版本
            u_int8_t ip_tos;              // 服务类型
            u_int16_t ip_len;             // 总长度
            u_int16_t ip_id;              // 标识
            u_int16_t ip_off;             // 标志和段偏移
            u_int8_t ip_ttl;              // 生存时间
            u_int8_t ip_p;                // 协议
            u_int16_t ip_sum;             // 校验和
            struct in_addr ip_src;        // 源IP地址
            struct in_addr ip_dst;        // 目的IP地址
        };

        // 定义TCP头部结构，20字节
        struct my_tcp_header {
            u_int16_t th_sport;           // 源端口
            u_int16_t th_dport;           // 目的端口
            u_int32_t th_seq;             // 序列号
            u_int32_t th_ack;             // 确认号
            u_int8_t th_off : 4, th_x2 : 4; // 数据偏移和保留位
            u_int8_t th_flags;            // 标志
            u_int16_t th_win;             // 窗口大小
            u_int16_t th_sum;             // 校验和
            u_int16_t th_urp;             // 紧急指针
        };

        // 定义UDP头部结构，8字节
        struct my_udp_header {
            uint16_t SrcPort;    // 源端口号
            uint16_t DstPort;    // 目的端口号
            uint16_t len;        // 数据包长度
            uint16_t checkSum;   // 校验和
        };

        struct my_udp_header2 {
            u_int16_t SrcPort;    // 源端口号 ，u_int16_t和uint16_t的区别主要体现在定义来源和标准化程度上
            u_int16_t DstPort;    // 目的端口号
            uint16_t len;        // 数据包长度
            uint16_t checkSum;   // 校验和
        };

        // =============================================================================================== 行情报文
        // ------ 上期
        // MIRP 报文头=11个字段，24字节
        struct MIRPHeader
        {
            // 低4位为1，表示当前协议版本号为1，高4位中第4位为0，表示当前报文是本消息的最后一个报文
            uint8_t flag;            // 标识位和协议版本号。高4位为标识位，低4位为协议版本号，可以用来确认是否为消息的最后一个报文
            int8_t type_id;          // 报文类型，即消息类型，唯一代表一个消息种类，0x01 表示增量行情刷新消息
            uint16_t length;         // 报文体长度（不包括报文头）
            int32_t packet_no;       // 行情报文编号，唯一标记一个增量行情报文
            int16_t topic_id;        // 行情主题的主题代码
            uint16_t snap_millisec;  // 当前主题行情快照的毫秒级时间
            int32_t snap_no;         // 当前主题增量行情的快照编号
            uint32_t snap_time;      // 当前主题行情快照的秒级时间
            uint16_t comm_phase_no;  // 当前交易日从1980年01月01日开始的天数
            int8_t center_change_no; // 当前数据中心切换编号
            int8_t reserved;         // 保留字节
        };

        // ------ 大连
        // 9个字段，24字节
        struct DMDPHeader
        {
            uint16_t pkg_size;        // 报文长度。报文头和报文体总长度
            uint16_t pkg_type;        // 报文类型。唯一标记一种报文
            uint8_t version;          // 版本号。目前版本号为1。e8=1
            uint8_t flag;             // 消息结束标示符
            uint8_t mdg_no;           // 产品组号
            uint64_t start_seq_no;    // 开始消息编号
            uint8_t seq_num;          // 当flag不为0时，则此字段代表当前报文是当前行情消息的第几个报文
            uint64_t send_time;       //  L1、L2定时行情报文发送时间；UTC时间；精确到纳秒；其他报文中此字段为0
            int8_t reserved;          // 扩展长度字段。目前为0。42=0
        };



    };
#pragma pack()

} // ntp

#endif //NETWORK_TRAFFIC_PROCESSING_V2_PCAPUTILS_H
